#include "Irp.h"

NTSTATUS IrpGeneral(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    UNREFERENCED_PARAMETER(DeviceObject);
    UNREFERENCED_PARAMETER(Irp);
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}

NTSTATUS IrpDeviceControl(IN struct _DEVICE_OBJECT* DeviceObject, IN OUT struct _IRP* Irp)
{
    UNREFERENCED_PARAMETER(DeviceObject);

    NTSTATUS ntStatus = STATUS_SUCCESS;
    ULONG_PTR uInformation = 0;
    PIO_STACK_LOCATION pStackLocation = IoGetCurrentIrpStackLocation(Irp);
    ULONG uCode = pStackLocation->Parameters.DeviceIoControl.IoControlCode;
    ULONG uLen = pStackLocation->Parameters.DeviceIoControl.OutputBufferLength;
    PVOID pBuff = Irp->AssociatedIrp.SystemBuffer;
    HANDLE hEvent;
    KIRQL Irql;
    PLIST_ENTRY pEntry;
    PPROCESS_NAME ProcessName = NULL;

    switch (uCode)
    {
    case CTL_CODE_INIT:
    {
        hEvent = *((HANDLE*)pBuff);
        ntStatus = ObReferenceObjectByHandle(hEvent, EVENT_MODIFY_STATE, *ExEventObjectType, KernelMode,
            &g_pkEvent, NULL);
        if (STATUS_SUCCESS != ntStatus)
        {
            ERRPRINT(ObReferenceObjectByHandle, ntStatus);
            break;
        }

        break;
    }
    case CTL_CODE_GETINFO:
    {
        if (g_ProcessNameListHead.Flink == &g_ProcessNameListHead) break;

        KeAcquireSpinLock(&g_ListSpinLock, &Irql);
        pEntry = RemoveHeadList(&g_ProcessNameListHead);
        KeReleaseSpinLock(&g_ListSpinLock, Irql);

        ProcessName = CONTAINING_RECORD(pEntry, PROCESS_NAME, Entry);
        uInformation = strlen(ProcessName->strProcessName);
        if (uLen > uInformation)
        {
            RtlCopyMemory(pBuff, ProcessName->strProcessName, uInformation);
        }

        ExFreePoolWithTag(ProcessName, TAG_PROCESS_NAME);

        break;
    }
    default:
        ASSERTMSG(FALSE, __FUNCTION__);
        break;
    }

    Irp->IoStatus.Status = ntStatus;
    Irp->IoStatus.Information = uInformation;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return ntStatus;
}
